// Copyright (c) MatrixFramework. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Matrix.ServiceCommunication.Options;

namespace Matrix.ServiceCommunication.Authentication.ApiKey;

/// <summary>
/// API Key认证提供者
/// </summary>
public class ApiKeyAuthenticationProvider : IAuthenticationProvider
{
    private readonly IOptionsMonitor<ServiceCommunicationOptions> _options;
    private readonly ILogger<ApiKeyAuthenticationProvider> _logger;
    private readonly IMemoryCache _cache;
    private readonly ConcurrentDictionary<string, ApiKeyInfo> _apiKeys;
    private bool _disposed;

    public ApiKeyAuthenticationProvider(
        IOptionsMonitor<ServiceCommunicationOptions> options,
        ILogger<ApiKeyAuthenticationProvider> logger,
        IMemoryCache cache)
    {
        _options = options ?? throw new ArgumentNullException(nameof(options));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        _cache = cache ?? throw new ArgumentNullException(nameof(cache));
        _apiKeys = new ConcurrentDictionary<string, ApiKeyInfo>();

        // 订阅配置变更
        _options.OnChange(OnConfigurationChanged);

        // 初始化API Keys
        InitializeApiKeys();

        _logger.LogInformation("API Key认证提供者已初始化，共加载 {Count} 个API Key", _apiKeys.Count);
    }

    public Task<string> GetAccessTokenAsync(string serviceName, CancellationToken cancellationToken = default)
    {
        var options = _options.CurrentValue;
        var authOptions = options.Authentication;

        if (authOptions.Type != AuthenticationType.ApiKey)
        {
            _logger.LogDebug("认证类型不是API Key，返回空字符串");
            return Task.FromResult(string.Empty);
        }

        var apiKey = GetApiKeyForService(serviceName);
        if (string.IsNullOrEmpty(apiKey))
        {
            _logger.LogWarning("未找到服务 {ServiceName} 的API Key", serviceName);
            return Task.FromResult(string.Empty);
        }

        _logger.LogDebug("获取API Key成功，服务: {ServiceName}", serviceName);
        return Task.FromResult(apiKey);
    }

    public Task<string> RefreshTokenAsync(string serviceName, CancellationToken cancellationToken = default)
    {
        // API Key不需要刷新，直接返回新的Token
        return GetAccessTokenAsync(serviceName, cancellationToken);
    }

    public Task<bool> ValidateTokenAsync(string token, CancellationToken cancellationToken = default)
    {
        if (string.IsNullOrWhiteSpace(token))
        {
            return Task.FromResult(false);
        }

        try
        {
            var apiKeyInfo = _apiKeys.Values.FirstOrDefault(k => k.Key == token);
            if (apiKeyInfo == null)
            {
                _logger.LogWarning("未找到匹配的API Key");
                return Task.FromResult(false);
            }

            // 检查API Key是否启用
            if (!apiKeyInfo.Enabled)
            {
                _logger.LogWarning("API Key已禁用: {ApiKeyId}", apiKeyInfo.Id);
                return Task.FromResult(false);
            }

            // 检查API Key是否过期
            if (apiKeyInfo.ExpiresAt.HasValue && apiKeyInfo.ExpiresAt.Value < DateTime.UtcNow)
            {
                _logger.LogWarning("API Key已过期: {ApiKeyId}, 过期时间: {ExpiresAt}",
                    apiKeyInfo.Id, apiKeyInfo.ExpiresAt.Value);
                return Task.FromResult(false);
            }

            // 检查使用次数限制
            if (apiKeyInfo.MaxUsageCount.HasValue && apiKeyInfo.UsageCount >= apiKeyInfo.MaxUsageCount.Value)
            {
                _logger.LogWarning("API Key使用次数已达上限: {ApiKeyId}, 使用次数: {UsageCount}",
                    apiKeyInfo.Id, apiKeyInfo.UsageCount);
                return Task.FromResult(false);
            }

            // 增加使用次数
            apiKeyInfo.UsageCount++;
            apiKeyInfo.LastUsedAt = DateTime.UtcNow;

            _logger.LogDebug("API Key验证成功: {ApiKeyId}, 使用次数: {UsageCount}",
                apiKeyInfo.Id, apiKeyInfo.UsageCount);

            return Task.FromResult(true);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "API Token验证异常");
            return Task.FromResult(false);
        }
    }

    /// <summary>
    /// 生成新的API Key
    /// </summary>
    /// <param name="serviceName">服务名称</param>
    /// <param name="description">描述</param>
    /// <param name="expiresAt">过期时间</param>
    /// <param name="maxUsageCount">最大使用次数</param>
    /// <returns>生成的API Key信息</returns>
    public async Task<ApiKeyInfo> GenerateApiKeyAsync(
        string serviceName,
        string description,
        DateTime? expiresAt = null,
        int? maxUsageCount = null)
    {
        var apiKeyId = $"api_{serviceName}_{Guid.NewGuid():N}";
        var apiKeySecret = GenerateSecureApiKey();
        var apiKey = $"{apiKeyId}.{apiKeySecret}";

        var apiKeyInfo = new ApiKeyInfo
        {
            Id = apiKeyId,
            Key = apiKey,
            ServiceName = serviceName,
            Description = description,
            Enabled = true,
            CreatedAt = DateTime.UtcNow,
            ExpiresAt = expiresAt,
            MaxUsageCount = maxUsageCount,
            UsageCount = 0,
            LastUsedAt = null
        };

        _apiKeys[apiKeyInfo.Id] = apiKeyInfo;

        _logger.LogInformation("生成API Key成功: {ApiKeyId}, 服务: {ServiceName}",
            apiKeyInfo.Id, serviceName);

        return await Task.FromResult(apiKeyInfo);
    }

    /// <summary>
    /// 撤销API Key
    /// </summary>
    /// <param name="apiKeyId">API Key ID</param>
    /// <returns>是否成功撤销</returns>
    public async Task<bool> RevokeApiKeyAsync(string apiKeyId)
    {
        if (string.IsNullOrEmpty(apiKeyId))
        {
            return await Task.FromResult(false);
        }

        if (_apiKeys.TryRemove(apiKeyId, out var removedKey))
        {
            _logger.LogInformation("API Key已撤销: {ApiKeyId}", apiKeyId);
            return await Task.FromResult(true);
        }

        _logger.LogWarning("未找到要撤销的API Key: {ApiKeyId}", apiKeyId);
        return await Task.FromResult(false);
    }

    /// <summary>
    /// 获取API Key信息
    /// </summary>
    /// <param name="apiKeyId">API Key ID</param>
    /// <returns>API Key信息</returns>
    public async Task<ApiKeyInfo?> GetApiKeyInfoAsync(string apiKeyId)
    {
        if (string.IsNullOrEmpty(apiKeyId))
        {
            return await Task.FromResult<ApiKeyInfo?>(null);
        }

        _apiKeys.TryGetValue(apiKeyId, out var apiKeyInfo);
        return await Task.FromResult(apiKeyInfo);
    }

    /// <summary>
    /// 获取所有API Key
    /// </summary>
    /// <returns>API Key列表</returns>
    public async Task<IReadOnlyList<ApiKeyInfo>> GetAllApiKeysAsync()
    {
        var apiKeys = _apiKeys.Values.ToList().AsReadOnly();
        return await Task.FromResult(apiKeys);
    }

    private string GetApiKeyForService(string serviceName)
    {
        // 优先查找专门为该服务配置的API Key
        var serviceSpecificKey = _apiKeys.Values
            .FirstOrDefault(k => k.ServiceName.Equals(serviceName, StringComparison.OrdinalIgnoreCase) && k.Enabled);

        if (serviceSpecificKey != null)
        {
            return serviceSpecificKey.Key;
        }

        // 查找通用的API Key
        var genericKey = _apiKeys.Values
            .FirstOrDefault(k => string.IsNullOrEmpty(k.ServiceName) && k.Enabled);

        if (genericKey != null)
        {
            return genericKey.Key;
        }

        // 从配置中查找默认API Key
        var options = _options.CurrentValue.Authentication;
        if (!string.IsNullOrEmpty(options.ClientSecret))
        {
            return options.ClientSecret;
        }

        return string.Empty;
    }

    private void InitializeApiKeys()
    {
        var options = _options.CurrentValue.Authentication;

        // 如果配置了ClientSecret，创建一个默认的API Key
        if (!string.IsNullOrEmpty(options.ClientSecret))
        {
            var defaultApiKey = new ApiKeyInfo
            {
                Id = "default_api_key",
                Key = options.ClientSecret,
                ServiceName = string.Empty, // 通用API Key
                Description = "默认API Key（从配置文件加载）",
                Enabled = true,
                CreatedAt = DateTime.UtcNow,
                ExpiresAt = null,
                MaxUsageCount = null,
                UsageCount = 0,
                LastUsedAt = null
            };

            _apiKeys[defaultApiKey.Id] = defaultApiKey;
            _logger.LogDebug("已加载默认API Key: {ApiKeyId}", defaultApiKey.Id);
        }

        // 这里可以扩展为从数据库或其他配置源加载API Keys
        // 例如：LoadApiKeysFromDatabase();
    }

    private string GenerateSecureApiKey()
    {
        using var rng = RandomNumberGenerator.Create();
        var bytes = new byte[32]; // 256位
        rng.GetBytes(bytes);
        return Convert.ToBase64String(bytes).Replace("+", "-").Replace("/", "_").TrimEnd('=');
    }

    private void OnConfigurationChanged(ServiceCommunicationOptions newOptions)
    {
        // 配置变更时重新初始化API Keys
        _apiKeys.Clear();
        InitializeApiKeys();

        _logger.LogInformation("API Key配置已变更，已重新初始化API Keys");
    }

    public void Dispose()
    {
        if (_disposed) return;

        _disposed = true;
        _apiKeys.Clear();
        _cache.Compact(1.0);

        _logger.LogDebug("API Key认证提供者已释放");
    }
}

/// <summary>
/// API Key信息
/// </summary>
public class ApiKeyInfo
{
    /// <summary>
    /// API Key ID
    /// </summary>
    public string Id { get; set; } = string.Empty;

    /// <summary>
    /// API Key值
    /// </summary>
    public string Key { get; set; } = string.Empty;

    /// <summary>
    /// 服务名称
    /// </summary>
    public string ServiceName { get; set; } = string.Empty;

    /// <summary>
    /// 描述
    /// </summary>
    public string Description { get; set; } = string.Empty;

    /// <summary>
    /// 是否启用
    /// </summary>
    public bool Enabled { get; set; } = true;

    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime CreatedAt { get; set; }

    /// <summary>
    /// 过期时间（可选）
    /// </summary>
    public DateTime? ExpiresAt { get; set; }

    /// <summary>
    /// 最大使用次数（可选）
    /// </summary>
    public int? MaxUsageCount { get; set; }

    /// <summary>
    /// 使用次数
    /// </summary>
    public int UsageCount { get; set; }

    /// <summary>
    /// 最后使用时间
    /// </summary>
    public DateTime? LastUsedAt { get; set; }

    /// <summary>
    /// 元数据
    /// </summary>
    public Dictionary<string, object> Metadata { get; set; } = new();
}